/*
 * 创建时间：2015年7月27日 
 */
package com.tuanzi.loan.workflow.service.impl;

import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import lombok.extern.slf4j.Slf4j;

import org.activiti.engine.ActivitiException;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.RuntimeServiceImpl;
import org.activiti.engine.impl.bpmn.behavior.ExclusiveGatewayActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.ParallelGatewayActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.ReceiveTaskActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.bpmn.helper.ClassDelegate;
import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.javax.el.ExpressionFactory;
import org.activiti.engine.impl.javax.el.ValueExpression;
import org.activiti.engine.impl.juel.ExpressionFactoryImpl;
import org.activiti.engine.impl.juel.SimpleContext;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.delegate.ActivityBehavior;
import org.activiti.engine.impl.pvm.delegate.SubProcessActivityBehavior;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskInfo;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.tuanzi.loan.business.entity.system.SystemUser;
import com.tuanzi.loan.core.exception.SystemException;
import com.tuanzi.loan.core.vo.PageSearcher;
import com.tuanzi.loan.vo.request.system.ProcessInstanceSearchRequest;
import com.tuanzi.loan.workflow.cmd.GenerateFlowImageCmd;
import com.tuanzi.loan.workflow.cmd.JumpActivityCmd;
import com.tuanzi.loan.workflow.common.ActivityType;
import com.tuanzi.loan.workflow.common.EndEventType;
import com.tuanzi.loan.workflow.entity.HistoryTask;
import com.tuanzi.loan.workflow.entity.OperateType;
import com.tuanzi.loan.workflow.entity.Opinion;
import com.tuanzi.loan.workflow.listener.WorkflowListener;
import com.tuanzi.loan.workflow.repository.HistoryTaskRepository;
import com.tuanzi.loan.workflow.repository.ProcessInstanceRepository;
import com.tuanzi.loan.workflow.service.OpinionService;
import com.tuanzi.loan.workflow.service.WorkflowBaseService;
import com.tuanzi.loan.workflow.service.WorkflowManagerService;
import com.tuanzi.loan.workflow.service.WorkflowProcessorService;
import com.tuanzi.loan.workflow.vo.ActivityResponse;
import com.tuanzi.loan.workflow.vo.AssigneeResponse;
import com.tuanzi.loan.workflow.vo.ProcessInstanceResponse;
import com.tuanzi.loan.workflow.vo.RouterResponse;
import com.tuanzi.loan.workflow.vo.TaskResponse;
import com.tuanzi.loan.workflow.vo.TrackingResponse;
import com.tuanzi.loan.workflow.vo.request.CommitTaskRequest;
import com.tuanzi.loan.workflow.vo.request.SendTaskRequest;

/**
 * @author Ray
 * @date 2018/01/16
 */
@Slf4j
@Service
@Transactional
public class WorkflowProcessorServiceImpl extends WorkflowBaseService implements WorkflowProcessorService {

	@Autowired
	private OpinionService opinionService;
	@Autowired
	private WorkflowManagerService workflowManagerService;
	@Autowired
	private ProcessInstanceRepository processInstanceRepository;
	@Autowired
	private HistoryTaskRepository historyTaskRepository;

	// @Autowired
	// private WorkflowManagerService workflowManagerService;
	// @Autowired
	// private ProcInstFormParamService procInstFormParamService;
	// @Autowired
	// private FormBindingService formBandingService;
	// @Autowired
	// private TodoReadLogService todoReadLogService;
	// @Autowired
	// private DelegationService delegationService;
	// @Autowired
	// private WorkflowScriptService workflowScriptService;
	// @Autowired
	// private OpinionService opinionService;
	// @Autowired
	// private ActivitiCommonService activitiCommonService;
	// @Autowired
	// private RoleService roleService;
	// @Autowired
	// private EmployeeService employeeService;
	// @Autowired
	// private ProcessInfoService processInfoService;

	// @Resource
	// private TransferLogService transferLogService;
	//

	@Override
	public ProcessInstanceResponse findProcessInstanceByProcInstId(String procInstId) {
		return structureProcessInstanceResponseFrom(runtimeService.createProcessInstanceQuery()
				.processInstanceId(procInstId).singleResult());
	}

	@Override
	public List<ProcessInstanceResponse> findProcessInstanceByBusinessKey(String businessKey) {
		return structureProcessInstanceResponseFrom(runtimeService.createProcessInstanceQuery()
				.processInstanceBusinessKey(businessKey).list());
	}

	private ProcessInstanceResponse startProcessInstance(String procDefKey, String busiKey, String title,
			String account, String assignee, Map<String, Object> variables) {

		ProcessDefinition procDef = repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey)
				.latestVersion().singleResult();
		if (procDef == null) {
			throw new SystemException("启动流程错误：流程[ " + procDefKey + " ]不存在！");
		}

		// 验证用户是否有启动权限
		// TODO 验证是否有启动流程权限
		// ActivityVO actVO = this.getFistActivity(procDef);
		// if (actVO != null && !this.hasActivityRight(procDef.getId(),
		// actVO.getActivityId(), user)) {
		// throw new ServiceException(ErrorResponseEnum.INVOKE_ERROR.getCode(),
		// "启动流程错误：用户[ " + user.getUserName() + " ]没有启动流程的权限！");
		// }
		//
		// if (actVO != null &&
		// CollectionUtils.isEmpty(actVO.getAssigneeList())) {
		// throw new ServiceException(ErrorResponseEnum.INVOKE_ERROR.getCode(),
		// "启动流程错误：没有配置执行者");
		// }

		try {

			identityService.setAuthenticatedUserId(account);

			ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(procDefKey, busiKey, variables);
			runtimeService.setProcessInstanceName(processInstance.getId(), title);

			TaskQuery taskQuery = taskService.createTaskQuery();
			List<Task> tasks = taskQuery.processInstanceId(processInstance.getId())
					.taskCandidateUser(StringUtils.isBlank(assignee) ? account : assignee).list();
			if (tasks != null) {
				for (Task task : tasks) {
					taskService.claim(task.getId(), StringUtils.isBlank(assignee) ? account : assignee);
				}
			}

			// 绑定流程实例与表单参数
			return structureProcessInstanceResponseFrom(processInstance);
		} catch (ActivitiException e) {
			log.error(e.getMessage(), e);
			throw new SystemException("启动流程【 " + procDefKey + " 】错误或流程已被禁用");
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new SystemException(e.getMessage(), e);
		}

	}

	// @Override
	// public ProcessInstanceVO startAutoProcessInstance(String procDefKey,
	// String
	// busiKey, String title,
	// Map<String, Object> variables, Map<String, String> urlParam) {
	// ProcessDefinitionQuery procDefQuery =
	// repositoryService.createProcessDefinitionQuery();
	// ProcessDefinition procDef =
	// procDefQuery.processDefinitionKey(procDefKey).latestVersion().singleResult();
	// if (procDef == null) {
	// throw new
	// ServiceException(ErrorResponseEnum.REQUEST_PARAMETER_INVALID.getCode(),
	// "启动流程错误：流程[ " + procDefKey + " ]不存在！");
	// }
	//
	// ProcessInstance pi = runtimeService.startProcessInstanceByKey(procDefKey,
	// busiKey, variables);
	// //runtimeService.setProcessInstanceName(pi.getId(), title);已结束
	//
	// // 返回流程实例对象
	// ProcessInstanceVO processInstanceVO = new ProcessInstanceVO();
	// BeanUtils.copyProperties(pi, processInstanceVO);
	//
	// return processInstanceVO;
	// }
	//
	//
	@Override
	public TaskResponse findTask(String procInstId, String account) {
		Task task = taskService.createTaskQuery().processInstanceId(procInstId).taskAssignee(account).singleResult();// 指定个人任务查询，指定办理人
		return this.structureTaskResponseFrom(task);
	}

	@Override
	public TaskResponse findTask(String taskId) {
		Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
		return structureTaskResponseFrom(task);
	}

	@Override
	public TaskResponse findHistoricalTask(String taskId) {
		HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().taskId(taskId)
				.singleResult();
		return structureTaskResponseFrom(historicTaskInstance);
	}

	private TaskResponse structureTaskResponseFrom(TaskInfo task) {
		if (task == null) {
			return null;
		}

		TaskResponse taskResponse = new TaskResponse();
		taskResponse.setProcInstId(task.getProcessInstanceId());
		taskResponse.setProcDefId(task.getProcessDefinitionId());
		taskResponse.setTaskName(task.getName());
		taskResponse.setId(task.getId());
		taskResponse.setExecutionId(task.getExecutionId());
		taskResponse.setAssignee(task.getAssignee());
		taskResponse.setTaskDefinitionKey(task.getTaskDefinitionKey());
		taskResponse.setCreateTime(task.getCreateTime());

		ProcessInstanceResponse processInstanceResponse = findProcessInstanceByProcInstId(task.getProcessInstanceId());
		taskResponse.setProcDefName(processInstanceResponse.getName());
		taskResponse.setBusinessKey(processInstanceResponse.getBusinessKey());

		return taskResponse;
	}

	private ProcessInstanceResponse structureProcessInstanceResponseFrom(ProcessInstance processInstance) {
		ProcessInstanceResponse response = new ProcessInstanceResponse();
		BeanUtils.copyProperties(processInstance, response);
		return response;
	}

	private List<ProcessInstanceResponse> structureProcessInstanceResponseFrom(List<ProcessInstance> processInstances) {
		return processInstances.stream().map(this::structureProcessInstanceResponseFrom).collect(Collectors.toList());
	}

	@Override
	public void approve(CommitTaskRequest request) {
		this.setVariable(request.getProcInstId(), "operateType", OperateType.APPROVE);

		request.getOpinion().setOperateType(OperateType.APPROVE);
		opinionService.saveOrUpdate(request.getOpinion());

		this.sendTask(structureSendTaskRequest(request));
	}

	@Override
	public void cancel(CommitTaskRequest request) {
		this.setVariable(request.getProcInstId(), "operateType", OperateType.CANCEL);

		request.getOpinion().setOperateType(OperateType.CANCEL);
		opinionService.saveOrUpdate(request.getOpinion());

		this.sendTask(structureSendTaskRequest(request));
	}

	@Override
	public void reject(CommitTaskRequest request) {
		this.setVariable(request.getProcInstId(), "operateType", OperateType.REJECT);
	}

	@Override
	public void back(String procInstId, String taskId) {
		this.setVariable(procInstId, "operateType", OperateType.BACK);
		TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();
		TaskResponse laskTaskVO = this.findLastFinishedTask(taskEntity.getProcessInstanceId(), taskId,
				taskEntity.getCreateTime());
		this.back(taskId, laskTaskVO.getTaskDefinitionKey(), laskTaskVO.getAssignee());
	}

	@Override
	public void pass(CommitTaskRequest request) {
		this.setVariable(request.getProcInstId(), "operateType", OperateType.PASS);

		request.getOpinion().setOperateType(OperateType.PASS);
		opinionService.saveOrUpdate(request.getOpinion());

		this.sendTask(structureSendTaskRequest(request));
	}

	private SendTaskRequest structureSendTaskRequest(CommitTaskRequest request) {
		SendTaskRequest sendTaskRequest = new SendTaskRequest();
		sendTaskRequest.setProcDefId(request.getProcDefId());
		sendTaskRequest.setProcInstId(request.getProcInstId());
		sendTaskRequest.setTaskId(request.getTaskId());
		sendTaskRequest.setNextAssigneeAccount(request.getNextAssigneeAccount());
		sendTaskRequest.setVariables(getVariable(request.getProcInstId()));
		ActivityResponse activityResponse = findActivity(request.getProcInstId(), request.getTaskDefinitionKey());
		sendTaskRequest.setPreExclusiveGatewayId(getPreExclusiveGatewayId(activityResponse));

		if (StringUtils.isNotBlank(request.getNextActivityId())) {
			sendTaskRequest.setNextActivityId(request.getNextActivityId());
		} else {
			sendTaskRequest.setNextActivityId(getNextActivityId(activityResponse));
		}

		return sendTaskRequest;
	}

	private String getPreExclusiveGatewayId(ActivityResponse activityResponse) {
		if (CollectionUtils.isNotEmpty(activityResponse.getPostRouters())) {
			String preExclusiveGatewayId = activityResponse.getPostRouters().get(0).getPreExclusiveGatewayId();

			if (StringUtils.isNotBlank(preExclusiveGatewayId)) {
				// if (MapUtils.isEmpty(variables)) {
				// // gateway但却不存在流程变量，肯定有设置错误问题
				// throw new SystemException("存在排他网关,但流程变量集合为空");
				// }
				return preExclusiveGatewayId;
			}
		}

		return null;
	}

	private String getNextActivityId(ActivityResponse activityResponse) {
		String nextActivityId = StringUtils.EMPTY;

		for (RouterResponse routerVO : activityResponse.getPostRouters()) {
			if (!routerVO.getToActivityId().contains("end")) {
				nextActivityId = routerVO.getToActivityId();
				break;
			}
		}
		// 如果仍为空，说明下一节点是结束节点
		if (StringUtils.isEmpty(nextActivityId)) {
			nextActivityId = activityResponse.getPostRouters().get(0).getToActivityId();
		}

		return nextActivityId;
	}

	//
	// private SendRequest buildRefusalSendRequest(CommitRequest request) {
	// TaskVO task = this.findTask(request.getTaskId());
	// if (task == null) {
	// throw new ServiceException(ErrorResponseEnum.SYSTEM_ERROR.getCode(),
	// "当前环节已经审批过！");
	// }
	// request.setProcDefId(task.getProcDefId());
	// String curActivityId = task.getTaskDefinitionKey();
	// // 获取当前活动对象
	// Map<String, Object> variables =
	// this.getVariable(request.getProcInstId());
	// ActivityVO curActivityVO =
	// workflowManagerService.getActivity(task.getProcDefId(), curActivityId,
	// variables);
	//
	// SendRequest sendRequest = new SendRequest();
	// sendRequest.setProcInstId(request.getProcInstId());
	// sendRequest.setProcDefId(task.getProcDefId());
	// sendRequest.setCurTaskId(task.getId());
	// sendRequest.setCurUserId(request.getCreatorId().toString());
	//
	// if (curActivityVO.getPostRouters().size() == 1 &&
	// !curActivityVO.getPostRouters().get(0).getToActivityId().contains("endevent"))
	// { // 如果出口只有一个，说明不存在拒绝节点
	// throw new
	// ServiceException(ErrorResponseEnum.REQUEST_PARAMETER_INVALID.getCode(),
	// "不存在拒绝的节点");
	// } else {
	// RouterVO refusalRoute = null;
	// for (RouterVO routerVO : curActivityVO.getPostRouters()) {
	// if (routerVO.getToActivityId().contains("end")) {
	// refusalRoute = routerVO;
	// break;
	// }
	// }
	// if (null == refusalRoute) {
	// throw new
	// ServiceException(ErrorResponseEnum.REQUEST_PARAMETER_INVALID.getCode(),
	// "不存在拒绝的节点");
	// }
	//
	// if (null == refusalRoute.getPreExclusiveGatewayId()) {
	// sendRequest.setNextActivityId(refusalRoute.getToActivityId());
	// } else {
	// sendRequest.setNextActivityId(curActivityVO.getPostRouters().get(0).getPreExclusiveGatewayId());
	// }
	// }
	// return sendRequest;
	// }
	//
	public void sendTask(SendTaskRequest request) {
		TaskResponse taskResponse = findTask(request.getTaskId());
		if (taskResponse == null) {
			throw new SystemException("任务不存在：taskId = " + request.getTaskId());
		}

		// 设置任务流程变量
		if (request.getVariables() == null) {
			request.setVariables(Maps.newHashMap());
		}

		// 完成当前任务
		String outcome = null;
		// 判断分支的情况
		if (StringUtils.isBlank(request.getPreExclusiveGatewayId())) {
			outcome = request.getNextActivityId();
		} else {
			outcome = request.getPreExclusiveGatewayId();
		}

		request.getVariables().put("outcome", outcome);// outcome用于控制多个出口的情况
		// taskService.setVariablesLocal(sendVO.getCurTaskId(),sendVO.getVariables());//限制变量的生命周期在本任务内
		taskService.complete(request.getTaskId(), request.getVariables());
		// 根据发送设置，指派下一任务处理人
		// 处理group的情况，人的情况不需要处理
		if (StringUtils.isBlank(request.getNextAssigneeAccount())) {
			// 送结束，或使用流程变量设置assignee
			return;
		}

		String[] nextAssignees = StringUtils.split(request.getNextAssigneeAccount(), ",");

		for (String nextAssignee : nextAssignees) {
			List<Task> tasks = taskService.createTaskQuery().processInstanceId(request.getProcInstId())
					.taskCandidateUser(nextAssignee).list();

			if (CollectionUtils.isEmpty(tasks)) {
				return;
			}
			for (Task nextTask : tasks) {
				if (nextTask.getTaskDefinitionKey().endsWith(request.getNextActivityId())
						&& StringUtils.isBlank(nextTask.getAssignee())) {
					SystemUser systemUser = systemUserService.findOneByAccount(nextAssignee);
					if (this.hasActivityRight(nextTask.getProcessDefinitionId(), nextTask.getTaskDefinitionKey(),
							nextAssignee)) {
						taskService.claim(nextTask.getId(), nextAssignee);
						// try {
						// // 判断nextTask的执行者是否配置了代理人
						// ProcessDefinitionQuery procDefQuery =
						// repositoryService.createProcessDefinitionQuery();
						// ProcessDefinition procDef =
						// procDefQuery.processDefinitionId(nextTask.getProcessDefinitionId()).singleResult();
						// BaseResponse<DelegationResponse> delegationResponse =
						// delegationService.find(procDef.getKey(), naa, new
						// Date());
						// if (delegationResponse.getResult().isSuccess()) {
						// taskService.delegateTask(nextTask.getId(),
						// delegationResponse.getResult().getData().getAgencyAccount());
						// activitiCommonService.updateBy(DelegationState.RESOLVED.toString(),
						// nextTask.getId(), nextTask.getProcessInstanceId());
						// }
						// } catch (Exception e) {
						// logger.error(e.getMessage(), e);
						// }
					} else {
						throw new RuntimeException("发送任务失败：下一步【" + nextTask.getName() + "】执行人【" + systemUser.getName()
								+ "】没有执行权限！");
					}

					// assigneeResult = true;
					break;
				}
			}
			/*
			 * if (!assigneeResult) { throw new
			 * Exception("后续处理人指派错误，找不到环节：nextActivityId=" +
			 * sendVO.getNextActivityId()); }
			 */
		}
	}

	//
	//
	// @Override
	// public void callBack(String taskId) {
	// // Task task =
	// processEngine.getTaskService().createTaskQuery().taskId(taskId).singleResult();//已成历史任务
	// HistoricTaskInstance task =
	// historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
	//
	// // 获取该任务的下一个活动是否正在执行
	// List<ActivityVO> actVOList =
	// this.getNextActivity(task.getProcessInstanceId(),
	// task.getTaskDefinitionKey());
	// for (ActivityVO activityVO : actVOList) {
	// List<Execution> exeList = runtimeService.createExecutionQuery().
	// processInstanceId(task.getProcessInstanceId()).activityId(activityVO.getActivityId()).list();
	// if (exeList == null) {
	// throw new ServiceException(ErrorResponseEnum.INVOKE_ERROR.getCode(),
	// "发送任务已被执行，不能回退！");
	// }
	// }
	//
	// // 回退任务
	// List<Execution> exeList =
	// runtimeService.createExecutionQuery().processInstanceId(task.getProcessInstanceId()).list();
	// for (Execution exe : exeList) {
	// String currActivityId = exe.getActivityId();
	// JumpActivityCmd cmd = new JumpActivityCmd(task.getProcessInstanceId(),
	// task.getTaskDefinitionKey(), currActivityId);
	// runCmd(cmd);
	// }
	//
	// // 回退任务后分配执行人
	// Task backTask =
	// taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId())
	// .taskDefinitionKey(task.getTaskDefinitionKey()).singleResult();
	// taskService.claim(backTask.getId(), task.getAssignee());
	// }
	//
	/**
	 * 功能：执行Activiti命令
	 *
	 * @param cmd
	 *            命令对象
	 */
	private void runCmd(Command<Object> cmd) {
		((RuntimeServiceImpl) runtimeService).getCommandExecutor().execute(cmd);
	}

	//
	// @Transactional
	// @Override
	// public BaseResponse<String> reject(FormRejectRequest request) {
	// BaseResponse<String> response = new BaseResponse<>();
	//
	// TaskVO taskVO = this.findTask(request.getTaskId());
	// if (Objects.isNull(taskVO)){
	// throw new ServiceException(ErrorResponseEnum.SYSTEM_ERROR.getCode(),
	// "任务不存在！taskId=" + request.getTaskId());
	// }
	//
	// // 如果task是被代理，回退时应回退给委托人。原因：代理人与委托人可能是不同角色，代理人不是该回退的task的candidatedUser
	// TaskVO selectedTaskVO =
	// this.getFinishedTaskByTaskId(request.getProcInstId(),
	// request.getSelectedTaskId());
	//
	// if(org.apache.commons.lang.StringUtils.isNotEmpty(selectedTaskVO.getOwner()))
	// {
	// request.setTargetAssigneeAccount(selectedTaskVO.getOwner());
	// }
	//
	// // 保存审批意见
	// saveRejectOpinion(request);
	//
	//
	// this.setVariable(request.getProcInstId(), "operateType", "reject");
	//
	// // 拒绝回退
	// if
	// (org.apache.commons.lang.StringUtils.isBlank(request.getTargetActivityId()))
	// {
	// this.reject(request.getTaskId());
	// } else {
	// this.reject(request.getTaskId(), request.getTargetActivityId()
	// , request.getTargetAssigneeAccount());
	// }
	// response.setResult(new BaseResult<>(true, "回退成功"));
	// return response;
	//
	// }
	//
	// private void saveRejectOpinion(FormRejectRequest request) {
	// // 保存审批意见
	// OpinionQueryRequest opinionQueryRequest = new OpinionQueryRequest();
	// opinionQueryRequest.setTaskId(request.getTaskId());
	// opinionQueryRequest.setProcDefId(request.getProcInstId());
	// opinionQueryRequest.setUserId(request.getCreatorId());
	// BaseResponse<OpinionResponse> opinionResponse =
	// opinionService.getOpinion(opinionQueryRequest);
	// OpinionResponse opinion = opinionResponse.getResult().getData();
	// OpinionSaveOrUpdateReqeust opinionSaveOrUpdateReqeust = new
	// OpinionSaveOrUpdateReqeust();
	// if (request.getRejectType() == RejectType.WITHDRAW) {
	// String withdrawStr = "提回";
	// if (opinionResponse.getResult().isSuccess()) {
	// ObjUtil.objectToObject(opinion, opinionSaveOrUpdateReqeust);
	// }
	// opinionSaveOrUpdateReqeust.setProcInstId(request.getProcInstId());
	// opinionSaveOrUpdateReqeust.setTaskId(request.getTaskId());
	// opinionSaveOrUpdateReqeust.setOpinionStatus(OpinionResponse.STATUS_SUBMIT);
	// BossUserResponse user =
	// userService.getUserByUserId(request.getCreatorId()).getResult().getData();
	// opinionSaveOrUpdateReqeust.setOperateResult(withdrawStr);
	// opinionSaveOrUpdateReqeust.setContent(user.getUserName() + withdrawStr);
	// opinionService.saveOrUpdate(opinionSaveOrUpdateReqeust);
	// } else {
	// if (opinionResponse.getResult().isSuccess()) {
	// ObjUtil.objectToObject(opinion, opinionSaveOrUpdateReqeust);
	// }
	// opinionSaveOrUpdateReqeust.setOpinionStatus(OpinionResponse.STATUS_SUBMIT);
	// opinionSaveOrUpdateReqeust.setProcInstId(request.getProcInstId());
	// opinionSaveOrUpdateReqeust.setTaskId(request.getTaskId());
	// AssigneeDefinitionGetRequest assigneeDefinitionGetRequest = new
	// AssigneeDefinitionGetRequest();
	// assigneeDefinitionGetRequest.setProcInstId(opinionSaveOrUpdateReqeust.getProcInstId());
	// assigneeDefinitionGetRequest.setTaskName(opinionSaveOrUpdateReqeust.getTaskName());
	// BaseResponse<String> assigneeDefResponse =
	// this.getAssigneeDefinition(assigneeDefinitionGetRequest);
	// opinionSaveOrUpdateReqeust.setRoleName(assigneeDefResponse.getResult().getData());
	// opinionService.saveOrUpdate(opinionSaveOrUpdateReqeust);
	// }
	//
	//
	// }
	//
	public void back(String taskId, String targetActivityId, String lastAccount) {
		TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();
		if (taskEntity == null) {
			throw new SystemException("任务实例不存在 : " + taskId);
		}
		// TODO:查询本节点发起的会签任务，并结束
		// 查找所有并行任务节点，同时驳回
		List<Task> taskList = taskService.createTaskQuery().processInstanceId(taskEntity.getProcessInstanceId())
				.taskDefinitionKey(taskEntity.getTaskDefinitionKey()).list();
		for (Task task : taskList) {
			this.jumpActivityBack(task.getProcessInstanceId(), task.getId(), targetActivityId,
					task.getTaskDefinitionKey(), lastAccount);
		}
	}

	@Override
	public void jumpActivity(String procInstId, String targetActivityId, String jumpOriginActivityId,
			String targetActivityAssigneeAccount) {
		JumpActivityCmd cmd = new JumpActivityCmd(procInstId, targetActivityId, jumpOriginActivityId);
		runCmd(cmd);
		// 任务拾取(针对角色)
		if (StringUtils.isBlank(targetActivityAssigneeAccount)) {
			return;
		}
		List<Task> tasks = taskService.createTaskQuery().processInstanceId(procInstId)
				.taskCandidateUser(targetActivityAssigneeAccount).list();
		if (tasks != null) {
			for (Task task : tasks) {
				taskService.claim(task.getId(), targetActivityAssigneeAccount);
			}
		}
	}

	@Override
	public void jumpActivityBack(String procInstId, String taskId, String targetActivityId,
			String jumpOriginActivityId, String targetActivityAssigneeAccount) {

		// 收集需要删除的前置活动
		List<TaskResponse> needRollBackTaskResponses = Lists.newArrayList();
		List<TaskResponse> passedTaskResponses = findPassedTaskResponse(taskId);

		for (TaskResponse passedTaskResponse : passedTaskResponses) {
			// 从头到尾检查一遍，直到到达跳转目标活动节点为止，活动key不相等的活动都要“回滚”
			if (!passedTaskResponse.getTaskDefinitionKey().equals(targetActivityId)) {
				needRollBackTaskResponses.add(passedTaskResponse);
			} else {
				// 相等就结束了
				break;
			}
		}

		runCmd(new JumpActivityCmd(procInstId, targetActivityId, jumpOriginActivityId));

		// 手工更新历史任务表
		for (TaskResponse needRollBackTaskResponse : needRollBackTaskResponses) {
			HistoryTask historyTask = historyTaskRepository.findOne(needRollBackTaskResponse.getId());
			if (historyTask == null) {
				historyTask.setDeleteReason(jumpOriginActivityId);
			}
		}

		// 任务拾取(针对角色)
		if (StringUtils.isBlank(targetActivityAssigneeAccount)) {
			log.error("流程回退! targetActivityAssigneeAccount为空！");
			return;
		}

		List<Task> tasks = taskService.createTaskQuery().processInstanceId(procInstId)
				.taskCandidateUser(targetActivityAssigneeAccount).list();

		if (CollectionUtils.isNotEmpty(tasks)) {
			for (Task task : tasks) {
				taskService.claim(task.getId(), targetActivityAssigneeAccount);
			}
		} else {
			log.error("流程回退，任务拾取tasks为空!");
		}
	}

	@Override
	public List<ActivityResponse> findNextActivity(String procInstId, String activityId) {
		ProcessInstanceResponse processInstanceResponse = findProcessInstanceByProcInstId(procInstId);

		if (processInstanceResponse == null) {
			throw new SystemException("流程实例不存在：procInstId=" + procInstId);
		}

		ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
				.getDeployedProcessDefinition(processInstanceResponse.getProcessDefinitionId());
		ActivityImpl activityImpl = def.findActivity(activityId);

		Map<String, Object> variables = runtimeService.getVariables(processInstanceResponse.getId());
		return this.getNextActivity(def, activityImpl, variables);
	}

	@Override
	public ActivityResponse findActivity(String procInstId, String activityId) {
		ProcessInstanceResponse processInstanceResponse = findProcessInstanceByProcInstId(procInstId);

		if (processInstanceResponse == null) {
			throw new SystemException("流程实例不存在：procInstId=" + procInstId);
		}

		ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
				.getDeployedProcessDefinition(processInstanceResponse.getProcessDefinitionId());

		ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);
		Map<String, Object> variables = runtimeService.getVariables(processInstanceResponse.getId());
		if (isUserTask(activityImpl)) {
			return this.mappingUserTaskActivityImpl2ActivityResponse(activityImpl, variables);
		} else {
			return this.mappingServiceTaskActivityImpl2ActivityResponse(activityImpl, null);
		}
	}

	//
	// @Override
	// public BaseResponse<List<ActivityVO>>
	// getAllActivity(AllActivityGetRequest
	// request) {
	// ProcessInstance procInst =
	// runtimeService.createProcessInstanceQuery().processInstanceId(request.getProcInstId()).singleResult();
	// if (procInst == null) {
	// throw new ServiceException(ErrorResponseEnum.INVOKE_ERROR.getCode(),
	// "流程实例不存在：procInstId=" + request.getProcInstId());
	// }
	//
	// BaseResponse<List<ActivityVO>> response = new BaseResponse<>();
	//
	// ProcessDefinitionEntity def = (ProcessDefinitionEntity)
	// ((RepositoryServiceImpl) repositoryService)
	// .getDeployedProcessDefinition(procInst.getProcessDefinitionId());
	// ActivityImpl currActivityImpl =
	// def.findActivity(request.getCurrActivityId());
	// List<ActivityImpl> allActivityImpl = def.getActivities();
	// List<ActivityVO> nextActivityList = new ArrayList<ActivityVO>();
	// Map<String, Object> variables =
	// runtimeService.getVariables(procInst.getId());
	//
	// for (ActivityImpl ai : allActivityImpl) {
	// if (ai == currActivityImpl) {
	// continue;//不添加当前节点
	// }
	// this.mapingActivityByBehavior(def, variables, nextActivityList, ai);
	// }
	// response.setResult(new BaseResult<>(nextActivityList));
	//
	// return response;
	// }
	//
	/**
	 * 功能：获取下一步的子节点（兼容分支流程）
	 *
	 * @param def
	 * @param activityImpl
	 * @param variables
	 * @return
	 * @throws Exception
	 */
	private List<ActivityResponse> getNextActivity(ProcessDefinitionEntity def, ActivityImpl activityImpl,
			Map<String, Object> variables) {
		List<ActivityResponse> nextActivityList = Lists.newArrayList();
		List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();
		for (PvmTransition tr : outTransitions) {
			if (tr.getProperty("conditionText") != null) {
				// 根据流程变量判断分支节点
				String varName = null;
				Object varValue = null;
				Set<String> varSet = variables.keySet();
				String conText = (String) tr.getProperty("conditionText");
				for (String var : varSet) {
					if (!"outcome".equals(var) && conText.indexOf(var) != -1) {
						// 表达式中包含变量
						varName = var;
						varValue = variables.get(var);
					}
				}
				if (varName != null && varValue != null) {
					ExpressionFactory factory = new ExpressionFactoryImpl();
					SimpleContext context = new SimpleContext();
					context.setVariable(varName, factory.createValueExpression(varValue, String.class));
					ValueExpression e = factory.createValueExpression(context,
							(String) tr.getProperty("conditionText"), boolean.class);
					if (((Boolean) e.getValue(context)).booleanValue() == false) {
						// 过滤不匹配的分支
						continue;
					}
				}
			}
			PvmActivity ac = tr.getDestination();
			// PvmActivity acSrc = tr.getSource();//此时无效
			ActivityImpl tmp = def.findActivity(ac.getId());
			this.mapingActivityByBehavior(def, variables, nextActivityList, tmp);
		}
		return nextActivityList;
	}

	//
	/**
	 * @param def
	 * @param variables
	 * @param nextActivityList
	 * @param tmp
	 * @return
	 * @throws Exception
	 */
	private void mapingActivityByBehavior(ProcessDefinitionEntity def, Map<String, Object> variables,
			List<ActivityResponse> nextActivityList, ActivityImpl tmp) {
		ActivityBehavior ab = tmp.getActivityBehavior();
		if (ab instanceof UserTaskActivityBehavior || ab instanceof MultiInstanceActivityBehavior) {
			ActivityResponse actVO = this.mappingUserTaskActivityImpl2ActivityResponse(tmp, variables);
			if (actVO != null) {
				actVO.setTaskVariables(variables);
				nextActivityList.add(actVO);
			}
		} else if (ab instanceof ExclusiveGatewayActivityBehavior || ab instanceof ParallelGatewayActivityBehavior) {
			// 递归获取子节点
			List<ActivityResponse> tmpList = getNextActivity(def, tmp, variables);
			nextActivityList.addAll(tmpList);
		} else if (ab instanceof SubProcessActivityBehavior) {
			// 获取子流程名称即可
			ActivityResponse actVO = new ActivityResponse();
			actVO.setId(tmp.getId());
			// actVO.setActivityId(tmp.get);
			actVO.setActivityName(tmp.getProperty("name").toString());
			actVO.setActivityType(tmp.getProperty("type").toString());
			actVO.setTaskVariables(variables);
			nextActivityList.add(actVO);
		} else if (ab instanceof ClassDelegate || tmp.getProperty("type").toString().equals("endEvent")
				|| ab instanceof ReceiveTaskActivityBehavior) {
			// 送结束
			ActivityResponse actVO = new ActivityResponse();
			actVO.setId(tmp.getId());
			actVO.setActivityId(tmp.getId());
			actVO.setActivityName(tmp.getProperty("name").toString());
			actVO.setActivityType(tmp.getProperty("type").toString());
			actVO.setAssignee(null);
			actVO.setAssigneeName(null);
			actVO.setTaskVariables(variables);
			nextActivityList.add(actVO);
		} else {
			// TODO：兼容其他情况
			log.info("未兼容的情况：" + ab);
		}
	}

	/**
	 * 职责：判断用户是否有权限执行节点
	 *
	 * @param procDefId
	 *            流程定义对象
	 * @param account
	 *            账户名
	 * @return
	 */
	private boolean hasActivityRight(String procDefId, String activityId, String account) {
		ActivityResponse activityResponse = workflowManagerService.findActivity(procDefId, activityId);
		if (activityResponse == null || CollectionUtils.isEmpty(activityResponse.getAssignees())) {
			return true;
		}

		boolean result = false;
		for (AssigneeResponse assigneeResponse : activityResponse.getAssignees()) {

			switch (assigneeResponse.getAssigneeType()) {
			case USER:
				result |= StringUtils.equals(assigneeResponse.getAssignee(), account);
				break;
			case ROLE:
				result |= roleService.hasRole(account, assigneeResponse.getAssignee());
				break;
			default:
				throw new SystemException("不支持执行者类型：AssigneeType = " + assigneeResponse.getAssigneeType());
			}
		}

		return result;
	}

	//
	// @Override
	// public List<FormBindingQueryResponse> parseBusiForms(String procDefId,
	// String
	// procInstId) {
	// FormBindingQueryRequest request = new FormBindingQueryRequest();
	// request.setProcDefId(procDefId);
	// DatatablesPageResponse<FormBindingQueryResponse> response =
	// formBandingService.listFormBanding(request);
	// List<FormBindingQueryResponse> formBandingVOs = response.getData();
	// for (FormBindingQueryResponse formBanding : formBandingVOs) {
	// String busiForm = formBanding.getBusiFormUrl();
	// String busiKey = getProcInstBusiKey(procInstId);
	//
	// if (StringUtils.isBlank(busiForm)) {
	// return null;
	// }
	//
	// // 获取表单参数
	// BaseResponse<FormInstParamResponse> formParamResponse =
	// procInstFormParamService.findByProcInstId(procInstId);
	// formBanding.setParsedBusiFormUrl(getFormBingUrl(busiForm, busiKey,
	// formParamResponse.getResult().getData()));
	// }
	// return formBandingVOs;
	// }
	//
	// // 获取表单请求的Action参数
	// // 最终拼接为xxx_Action?id=xx的形式
	// private String getFormBingUrl(String busiForm, String busiKey,
	// FormInstParamResponse formParam) {
	//
	// String actionIdName = formParam.getActionIdName();
	// String actionExtraParam = formParam.getActionExtraParam();
	//
	// // 检查buisForm是否已带参数
	// String[] busiFormPart = StringUtils.split(busiForm, "?");
	//
	// StringBuilder sb = new StringBuilder(busiFormPart[0]);
	// // 解析主键部分
	// String[] split = StringUtils.split(busiKey, ".");
	// if (isValidBusiKey(split)) {
	// String actionIdValue = split[1];
	// String actionExtraValue = null;
	// if (split.length >= 3) {
	// actionExtraValue = split[2];
	// }
	// sb.append("?").append(actionIdName).append("=").append(actionIdValue);
	// if (StringUtils.isNotBlank(actionExtraParam) &&
	// StringUtils.isNotBlank(actionExtraValue)) {
	// sb.append("&").append(actionExtraParam).append("=").append(actionExtraValue);
	// }
	// }
	// if (busiFormPart.length > 1) {
	// if (sb.toString().contains("?")) {
	// sb.append("&").append(busiFormPart[1]);
	// } else {
	// sb.append("?").append(busiFormPart[1]);
	// }
	// } else {
	// if (!sb.toString().contains("?")) {
	// sb.append("?1=1");
	// }
	// }
	// return sb.toString();
	// }
	//
	// private boolean isValidBusiKey(String[] split) {
	// return split != null && split.length >= 2;
	// }
	//
	// private String getProcInstBusiKey(String procInstId) {
	// return historyService.createHistoricProcessInstanceQuery().
	// processInstanceId(procInstId).singleResult().getBusinessKey();
	// }
	//
	// @Override
	// public void bindProcInstFormParam(ProcessInstanceVO pi,
	// Map<String, String> param) {
	// FormInstParam vo = new FormInstParam();
	// vo.setProcDefId(pi.getProcessDefinitionId());
	// String busiKey = pi.getBusinessKey();
	// if (StringUtils.endsWith(busiKey, ".")) {
	// throw new
	// ServiceException(ErrorResponseEnum.REQUEST_PARAMETER_INVALID.getCode(),
	// String.format("201,启动流程的业务表单参数有误,期望值[实体名.主键值],实际值[%s]", busiKey));
	// }
	// vo.setProcDefKey(busiKey);
	// vo.setProcInstId(pi.getId());
	// vo.setActivityId("");
	// vo.setActionIdName(param.get(FormInstParam.ACTION_ID_NAME));
	// vo.setActionExtraParam(param.get(FormInstParam.ACTION_EXTRA_PARAM));
	// procInstFormParamService.save(vo);
	// }
	//

	@Override
	public TaskResponse findFirstTaskByProcInstId(String procInstId) {
		return structureTaskResponseFrom(taskService.createTaskQuery().processInstanceId(procInstId).singleResult());
	}

	//
	// @Override
	// public String getProcInstIdByBusinessKey(String busiKey) {
	// List<HistoricProcessInstance> listPage =
	// historyService.createHistoricProcessInstanceQuery()
	// .processInstanceBusinessKey(busiKey)
	// .list();
	// // 还没发起过任何审批
	// if (CollectionUtils.isEmpty(listPage)) {
	// return null;
	// } else {
	// return listPage.get(0).getId();
	// }
	// }
	//
	// @Override
	// public String getActivitiIdByProcInstId(String procInstId) {
	// // modified by @huangza 兼容会签流程
	// List<Execution> executionList =
	// runtimeService.createExecutionQuery().processInstanceId(procInstId).list();
	// String activityId = null;
	// for (Execution execution : executionList) {
	// if (StringUtils.isEmpty(execution.getParentId()) &&
	// StringUtils.isNotEmpty(execution.getActivityId())) {
	// activityId = execution.getActivityId();
	// break;
	// } else {
	// activityId = execution.getActivityId();
	// }
	// }
	// return activityId;
	// }
	//
	// @Override
	// public List<ActivityVO> getActivityVOByProcInstId(String procInstId) {
	// HistoricProcessInstance hisProcInst =
	// historyService.createHistoricProcessInstanceQuery().processInstanceId(procInstId).singleResult();
	// //ProcessInstance procInst =
	// runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
	// if (hisProcInst == null) {
	// throw new ServiceException(ErrorResponseEnum.INVOKE_ERROR.getCode(),
	// "流程实例不存在，procInstId=" + procInstId);
	// }
	//
	// List<Execution> executionList =
	// runtimeService.createExecutionQuery().processInstanceId(procInstId).list();
	// List<ActivityVO> activityList = new ArrayList<ActivityVO>();
	//
	// if (CollectionUtils.isEmpty(executionList)) {
	// //已结束
	// ActivityVO actVO = new ActivityVO();
	// actVO.setActivityId("endevent");
	// actVO.setActivityName("结束");
	// activityList.add(actVO);
	// } else {
	// for (Execution execution : executionList) {
	// if (null == execution.getActivityId()) continue;
	// ActivityVO actVO =
	// workflowManagerService.getActivity(hisProcInst.getProcessDefinitionId(),
	// execution.getActivityId(), null);
	// // 设置executionId
	// actVO.setExecutionId(execution.getId());
	// activityList.add(actVO);
	// }
	// }
	//
	// return activityList;
	// }
	//
	//
	@Override
	public Map<String, Object> getVariable(String procInstId) {
		return runtimeService.getVariables(procInstId);
	}

	@Override
	public Object getVariable(String procInstId, String varName) {
		return runtimeService.getVariable(procInstId, varName);
	}

	//
	@Override
	public void setVariable(String procInstId, String varName, Object varValue) {
		runtimeService.setVariable(procInstId, varName, varValue);
	}

	@Override
	public List<TaskResponse> findAllFinishedTask(String procInstId) {
		List<TaskResponse> taskResponses = Lists.newArrayList();
		List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery()
				.processInstanceId(procInstId).orderByTaskCreateTime().desc().finished().list();
		for (HistoricTaskInstance historicTaskInstance : historicTaskInstances) {
			taskResponses.add(structureTaskResponseFrom(historicTaskInstance));
		}
		return taskResponses;
	}

	@Override
	public TaskResponse findFinishedTaskByTaskId(String procInstId, String taskId) {
		HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
				.processInstanceId(procInstId).taskId(taskId).finished().singleResult();

		if (historicTaskInstance == null) {
			return null;
		}

		return structureTaskResponseFrom(historicTaskInstance);
	}

	@Override
	public TaskResponse findLastFinishedTask(String procInstId, String currTaskId, Date startTime) {
		HistoricTaskInstanceQuery hisTaskQuery = this.historyService.createHistoricTaskInstanceQuery();
		HistoricTaskInstance curTask = hisTaskQuery.taskId(currTaskId).singleResult();

		ProcessDefinitionEntity procDefEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
				.getDeployedProcessDefinition(curTask.getProcessDefinitionId());

		ActivityImpl activityImpl = procDefEntity.findActivity(curTask.getTaskDefinitionKey());
		List<PvmTransition> incomePVM = activityImpl.getIncomingTransitions();

		// 取出节点的所有进来的线-倒序，最好排除当前节点（第一个）
		hisTaskQuery = this.historyService.createHistoricTaskInstanceQuery();
		List<HistoricTaskInstance> hisTaskInstList = hisTaskQuery.processInstanceId(procInstId).orderByTaskCreateTime()
				.desc().list();

		// 对于第一个环节，查询出来的可能为空,@liangqq
		if (CollectionUtils.isEmpty(hisTaskInstList)) {
			return null;
		}

		for (HistoricTaskInstance hisTaskInst : hisTaskInstList) {
			if (startTime.compareTo(hisTaskInst.getStartTime()) == 0) {
				for (PvmTransition pvmTransition : incomePVM) {
					// 对所有的线进行遍历
					ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition.getSource();
					// 判断上一个节点的类型
					if (pvmActivityImpl.getActivityBehavior() instanceof ExclusiveGatewayActivityBehavior
							|| pvmActivityImpl.getActivityBehavior() instanceof ParallelGatewayActivityBehavior // 兼容并行网关
																												// @author
																												// huangza
							|| pvmActivityImpl.getActivityBehavior() instanceof ClassDelegate) {
						// 如果是分支节点，则获取分支的输入环节
						List<PvmTransition> inTransitionList = pvmActivityImpl.getIncomingTransitions();
						for (PvmTransition pvmTransition2 : inTransitionList) {
							ActivityImpl pvmActivityImpl2 = (ActivityImpl) pvmTransition2.getSource();
							if (hisTaskInst.getTaskDefinitionKey().equals(pvmActivityImpl2.getId())) {
								return structureTaskResponseFrom(hisTaskInst);
							}
						}
					} else {
						if (hisTaskInst.getTaskDefinitionKey().equals(pvmActivityImpl.getId())) {
							return structureTaskResponseFrom(hisTaskInst);
						}
					}
				}
			}

			if (startTime.compareTo(hisTaskInst.getStartTime()) > 0) {
				return structureTaskResponseFrom(hisTaskInst);
			}
			// for (PvmTransition pvmTransition : incomePVM) {
			// taskVO = getLastFinishedTask(hisTaskInst, pvmTransition);
			// if (null != taskVO) return taskVO;
			// }
		}

		return null;
	}

	private TaskResponse findLastFinishedTask(HistoricTaskInstance hisTaskInst, PvmTransition pvmTransition) {
		// 对所有的线进行遍历
		ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition.getSource();
		// 判断上一个节点的类型
		if (pvmActivityImpl.getActivityBehavior() instanceof ExclusiveGatewayActivityBehavior
				|| pvmActivityImpl.getActivityBehavior() instanceof ParallelGatewayActivityBehavior // 兼容并行网关
																									// @author
																									// huangza
				|| pvmActivityImpl.getActivityBehavior() instanceof ClassDelegate) {
			// 如果是分支节点，则获取分支的输入环节
			List<PvmTransition> inTransitionList = pvmActivityImpl.getIncomingTransitions();
			for (PvmTransition pvmTransition2 : inTransitionList) {

				ActivityImpl pvmActivityImpl2 = (ActivityImpl) pvmTransition2.getSource();
				// 判断上一个节点的类型
				if (pvmActivityImpl2.getActivityBehavior() instanceof ExclusiveGatewayActivityBehavior
						|| pvmActivityImpl2.getActivityBehavior() instanceof ParallelGatewayActivityBehavior // 兼容并行网关
																												// @author
																												// huangza
						|| pvmActivityImpl2.getActivityBehavior() instanceof ClassDelegate) {
					continue;
				}

				return findLastFinishedTask(hisTaskInst, pvmTransition2);
			}

			for (PvmTransition pvmTransition2 : inTransitionList) {

				ActivityImpl pvmActivityImpl2 = (ActivityImpl) pvmTransition2.getSource();
				// 判断上一个节点的类型
				if (pvmActivityImpl2.getActivityBehavior() instanceof ExclusiveGatewayActivityBehavior
						|| pvmActivityImpl2.getActivityBehavior() instanceof ParallelGatewayActivityBehavior // 兼容并行网关
																												// @author
																												// huangza
						|| pvmActivityImpl2.getActivityBehavior() instanceof ClassDelegate) {
					return findLastFinishedTask(hisTaskInst, pvmTransition2);
				}
			}
		} else {
			if (hisTaskInst.getTaskDefinitionKey().equals(pvmActivityImpl.getId())) {
				return structureTaskResponseFrom(hisTaskInst);
			}
		}

		return null;
	}

	@Override
	public void addListener(WorkflowListener listener) {
		runtimeService.addEventListener(listener);
	}

	@Override
	public void removeListener(WorkflowListener listener) {
		runtimeService.removeEventListener(listener);
	}

	@Override
	public void endProcess(String procInstId) {
		ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId)
				.singleResult();

		if (processInstance == null) {
			throw new SystemException("流程实例不存在！procInstId = " + procInstId);
		}

		List<Task> tasks = taskService.createTaskQuery().processInstanceId(procInstId).list();

		if (CollectionUtils.isEmpty(tasks)) {
			throw new SystemException("流程已结束！procInstId = " + procInstId);
		}

		ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
				.getDeployedProcessDefinition(processInstance.getProcessDefinitionId());

		ActivityImpl endAct = def.findActivity("endevent1");
		if (null == endAct) {
			endAct = def.findActivity("endevent2");
		}
		for (Task task : tasks) {
			this.jumpActivity(procInstId, endAct.getId(), task.getTaskDefinitionKey(), null);
		}
	}

	@Override
	public void suspendProcess(String procInstId) {
		runtimeService.suspendProcessInstanceById(procInstId);
	}

	@Override
	public void activateProcess(String procInstId) {
		runtimeService.activateProcessInstanceById(procInstId);
	}

	//
	// @Override
	// public void resurgenceProcess(String procInstId) {
	// // 运用跳转的思路
	// //this.jumpActivity(procInstId, targetActivityId, jumpOriginActivityId,
	// targetActivityAssigneeAccount);
	// }
	//
	// @Override
	// public BaseResponse<BossUserResponse> getProcInstCurrUser(String
	// procInstId)
	// {
	// HistoricProcessInstance instance =
	// historyService.createHistoricProcessInstanceQuery().processInstanceId(procInstId).singleResult();
	// String account = instance.getStartUserId();
	// return userService.getBossUserByAccount(account);
	// }
	//
	// @Override
	// public TaskVO getProcInstCurrTask(String procInstId) {
	// Task task =
	// taskService.createTaskQuery().processInstanceId(procInstId).singleResult();
	// TaskVO taskvo = new TaskVO();
	// // 若流程已结束，task为null @zhangweihao
	// if (null != task) {
	// BeanUtils.copyProperties(task, taskvo);
	// taskvo.setTaskName(task.getName());
	// }
	// return taskvo;
	// }
	//
	// @Override
	// public List<TaskVO> getProcInstCurrTask(List<String> procInstIds) {
	// List<Task> tasks =
	// taskService.createTaskQuery().processInstanceIdIn(procInstIds).list();
	// List<TaskVO> taskVOs = new ArrayList<TaskVO>();
	//
	// for (Task task : tasks) {
	// TaskVO taskvo = new TaskVO();
	// BeanUtils.copyProperties(task, taskvo);
	// taskvo.setTaskName(task.getName());
	// taskVOs.add(taskvo);
	// }
	//
	// return taskVOs;
	// }
	//
	// @Override
	// public List<ProcessDefinitionVO> getAvailableProcDefList(BossUserResponse
	// user) {
	// if (user == null) {
	// throw new
	// ServiceException(ErrorResponseEnum.REQUEST_PARAMETER_INVALID.getCode(),
	// "用户参数不能为空！");
	// }
	// ProcessDefinitionQuery query =
	// repositoryService.createProcessDefinitionQuery();
	// List<ProcessDefinition> list = query.orderByProcessDefinitionVersion()
	// //.startableByUser(user.getUserAccount())//限制启动的人
	// .asc().list();// 使用流程定义的版本升序排列
	//
	// // 去重
	// Map<String, ProcessDefinition> map = new LinkedHashMap<String,
	// ProcessDefinition>();
	// if (list != null && list.size() > 0) {
	// for (ProcessDefinition pd : list) {
	// map.put(pd.getKey(), pd);
	// }
	// }
	//
	// List<ProcessDefinition> pdList = new
	// ArrayList<ProcessDefinition>(map.values());
	// List<ProcessDefinition> pdListDel = new ArrayList<ProcessDefinition>();
	// for (ProcessDefinition procDef : pdList) {
	// // 验证用户是否有启动权限
	// try {
	// ActivityVO actVO = this.getFistActivity(procDef);
	// if (!this.hasActivityRight(procDef.getId(), actVO.getActivityId(), user))
	// {
	// pdListDel.add(procDef);
	// //throw new Exception("启动流程错误：用户[ " + user.getUsername() +
	// " ]没有启动流程的权限！");
	// }
	// } catch (Exception e) {
	// this.logger.info(e.getMessage());
	// }
	// }
	// //只显示有权限启动的流程定义
	// if (!pdListDel.isEmpty()) {
	// pdList.removeAll(pdListDel);
	// }
	//
	// List<ProcessDefinitionVO> pdVOList = new
	// ArrayList<ProcessDefinitionVO>();
	// for (ProcessDefinition procDef : pdList) {
	// ProcessDefinitionVO procDefVO = mappingProcessDefinitionVO(procDef);
	// pdVOList.add(procDefVO);
	// }
	// return pdVOList;
	// }
	//
	//
	// @Override
	// public void deleteProcess(String procInstId, String deleteReason) {
	// /*
	// if (StringUtils.isBlank(procInstId)) {
	// throw new Exception("参数procInstId不能为空！");
	// }
	// if (StringUtils.isBlank(deleteReason)) {
	// throw new Exception("参数deleteReason不能为空！");
	// }
	// ProcessInstance procInst =
	// this.runtimeService.createProcessInstanceQuery()
	// .processInstanceId(procInstId)
	// .singleResult();
	// if (procInst == null) {
	// throw new Exception("流程实例不存在！procInstId=" + procInstId);
	// }
	//
	// this.runtimeService.deleteProcessInstance(procInstId, deleteReason);
	// */
	// // 如果只删除运行时的记录，不删除历史记录，则仍然在已办列表中查看到被删除的待办记录
	// // 改用删除全部流程信息
	// this.deleteProcessWithHistory(procInstId, deleteReason);
	// }
	//
	// @Override
	// public BaseResponse<Void> deleteProcessWithHistory(String procInstId,
	// String
	// deleteReason) {
	// if (StringUtils.isBlank(procInstId)) {
	// throw new
	// ServiceException(ErrorResponseEnum.REQUEST_PARAMETER_INVALID.getCode(),
	// "参数procInstId不能为空！");
	// }
	// if (StringUtils.isBlank(deleteReason)) {
	// throw new
	// ServiceException(ErrorResponseEnum.REQUEST_PARAMETER_INVALID.getCode(),
	// "参数deleteReason不能为空！");
	// }
	//
	// ProcessInstance procInst =
	// this.runtimeService.createProcessInstanceQuery()
	// .processInstanceId(procInstId)
	// .singleResult();
	//
	// HistoricProcessInstance procInstHis =
	// this.historyService.createHistoricProcessInstanceQuery()
	// .processInstanceId(procInstId)
	// .singleResult();
	//
	// if (procInst != null) {
	// this.runtimeService.deleteProcessInstance(procInstId, deleteReason);
	// }
	//
	// /** 需要先删除正在流转的实例，然后才能删除历史库的记录 */
	// if (procInstHis != null) {
	// this.historyService.deleteHistoricProcessInstance(procInstId);
	// } else {
	// throw new
	// ServiceException(ErrorResponseEnum.REQUEST_PARAMETER_INVALID.getCode(),
	// "流程实例不存在！");
	// }
	// return new BaseResponse<>(new BaseResult<>(true, "删除流程实例成功"));
	// }
	//
	@Override
	public List<TaskResponse> findPassedTaskResponse(String taskId) {
		HistoricTaskInstance hisTask = this.historyService.createHistoricTaskInstanceQuery().taskId(taskId)
				.singleResult();
		if (hisTask == null) {
			throw new SystemException("任务不存在 : " + taskId);
		}

		String procInstId = hisTask.getProcessInstanceId();
		List<TaskResponse> passedTaskResponses = Lists.newArrayList();
		Map<String, TaskResponse> passedTaskResponseMap = Maps.newLinkedHashMap();
		TaskResponse lastTaskResponse = this.findLastFinishedTask(procInstId, hisTask.getId(), hisTask.getStartTime());
		if (lastTaskResponse != null) {
			// 递归
			List<TaskResponse> result = this.findPassedTaskResponse(lastTaskResponse.getId());
			passedTaskResponseMap.put(lastTaskResponse.getTaskDefinitionKey(), lastTaskResponse);
			for (TaskResponse taskResponse : result) {
				passedTaskResponseMap.put(taskResponse.getTaskDefinitionKey(), taskResponse);
			}
		}
		passedTaskResponses.addAll(passedTaskResponseMap.values());
		return passedTaskResponses;
	}

	//
	// @Override
	// public void setProcInstVariablesWithCheck(String procInstId, String
	// varKey,
	// Object varValue) {
	// Object varObj = runtimeService.getVariable(procInstId, varKey);
	// if (varObj == null) {
	// this.setProcInstVariables(procInstId, varKey, varValue);
	// } else {
	// this.logger.info("流程实例[{}]流程变量[{}]已赋值，系统跳过此步骤", procInstId, varKey);
	// }
	// }
	//
	// @Override
	// public void setProcInstVariables(String procInstId, String varKey, Object
	// varValue) {
	// runtimeService.setVariable(procInstId, varKey, varValue);
	// }
	//
	//
	// @Override
	// public BaseResponse<Void> transferAssignee(AssigneeTransferRequest
	// request) {
	// BaseResponse<Void> baseResponse = new BaseResponse<>();
	// if (StringUtils.isBlank(request.getTaskId())) {
	// throw new
	// ServiceException(ErrorResponseEnum.REQUEST_PARAMETER_INVALID.getCode(),
	// "参数taskId不能为空！");
	// }
	// if (StringUtils.isBlank(request.getTransferUserAccount())) {
	// throw new
	// ServiceException(ErrorResponseEnum.REQUEST_PARAMETER_INVALID.getCode(),
	// "参数transferUserAccount不能为空！");
	// }
	//
	// Task task =
	// this.taskService.createTaskQuery().taskId(request.getTaskId()).singleResult();
	// if (task == null) {
	// throw new
	// ServiceException(ErrorResponseEnum.REQUEST_PARAMETER_INVALID.getCode(),
	// "任务不存在taskId=" + request.getTaskId());
	// }
	// // 判断当前用户是否是管理员
	// //boolean isAdministrator = userService.isAdministrator(orginUser);
	// // if
	// (!request.getOrginUser().getUserAccount().equals(task.getAssignee())) {
	// // throw new
	// ServiceException(ErrorResponseEnum.REQUEST_PARAMETER_INVALID.getCode(),
	// "任务转办异常：该任务没有分配给当前用户，不能转办！");
	// // }
	//
	// // 判断转办对象是否有流程权限
	// BaseResponse<BossUserResponse> response =
	// userService.getBossUserByAccount(request.getTransferUserAccount());
	// BossUserResponse user = response.getResult().getData();
	// boolean hasRight = true;//不限制
	// hasRight = this.hasActivityRight(task.getProcessDefinitionId(),
	// task.getTaskDefinitionKey(), user);
	// if (!hasRight) {
	// throw new
	// ServiceException(ErrorResponseEnum.REQUEST_PARAMETER_INVALID.getCode(),
	// "用户["
	// + user.getUserName() + "]没有执行权限!");
	// }
	//
	// // 执行转办
	// this.taskService.setAssignee(request.getTaskId(),
	// request.getTransferUserAccount());
	//
	// // 执行转办脚本
	// ScriptTaskQueryRequest queryRequest = new ScriptTaskQueryRequest();
	// queryRequest.setProcDefId(task.getProcessDefinitionId());
	// queryRequest.setActivityId(task.getTaskDefinitionKey());
	// queryRequest.setTaskType(ScriptTask.TASK_TYPE_TRANSFER);
	// BaseResponse<ScriptTaskResponse> taskResponse =
	// workflowScriptService.getScriptTaskVO(queryRequest);
	// ScriptTaskResponse scriptVO = taskResponse.getResult().getData();
	// ProcessInstance procInst =
	// this.runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
	// ProcessDefinition procDef =
	// this.repositoryService.getProcessDefinition(task.getProcessDefinitionId());
	// if (scriptVO != null) {
	// Map<String, Object> taskVariables =
	// this.processEngine.getTaskService().getVariables(task.getId());
	// taskVariables.put("transferUserAccount",
	// request.getTransferUserAccount());
	//
	//
	// Map<String, Object> param = new HashMap<String, Object>();
	// WebApplicationContext applicationContext =
	// ContextLoader.getCurrentWebApplicationContext();
	// WorkflowProcessorService workflowProcessorService =
	// applicationContext.getBean("workflowProcessorService",
	// WorkflowProcessorServiceImpl.class);
	// ServletRequestAttributes ra = (ServletRequestAttributes)
	// RequestContextHolder.getRequestAttributes();
	// HttpServletRequest httpServletRequest = ra.getRequest();
	// param.put("processor", workflowProcessorService); //预置流程处理服务对象
	// param.put("procInst", procInst); //预置流程实例对象
	// param.put("procDef", procDef); //预置流程定义对象
	// param.put("user", user); //预置当前用户对象
	// param.put("task", task); //预置当前任务对象
	// param.put("taskVariables", taskVariables);//预置当前任务变量
	// param.put("request", httpServletRequest); //预置request对象
	//
	// synchronized (this) {//同步代码块
	// ScriptTaskRunRequest runRequest = new ScriptTaskRunRequest();
	// runRequest.setScriptTaskResponse(scriptVO);
	// runRequest.setParam(param);
	// workflowScriptService.runScript(runRequest);
	// }
	// }
	//
	// // 保存审批意见
	//
	// OpinionSaveOrUpdateReqeust opinion = new OpinionSaveOrUpdateReqeust();
	// opinion.setUserId(request.getOrginUser().getId());
	// opinion.setProcInstId(task.getProcessInstanceId());
	// opinion.setTaskId(request.getTaskId());
	// opinion.setUserName(request.getOrginUser().getUserName());
	// String content = request.getOrginUser().getUserName() + " 转件给 " +
	// user.getUserName();
	// opinion.setContent(content);
	// opinion.setTaskName(task.getName() + "(转办)");
	// opinion.setOperateResult("转办");
	// opinion.setOpinionStatus(Opinion.STATUS_SUBMIT);
	// opinionService.saveOrUpdate(opinion);
	//
	// // 保存转办日志
	// TransferLogSaveRequest transferLogSaveRequest = new
	// TransferLogSaveRequest();
	// transferLogSaveRequest.setProcDefName(procDef.getName());
	// transferLogSaveRequest.setProcInstId(procInst.getId());
	// transferLogSaveRequest.setProcInstName(procInst.getName());
	// transferLogSaveRequest.setTaskName(task.getName());
	// transferLogSaveRequest.setTaskCreateTime(task.getCreateTime());
	// transferLogSaveRequest.setDeptId(request.getDeptId());
	// transferLogSaveRequest.setDeptName(request.getDeptName());
	// transferLogSaveRequest.setTransferAssigneeName(user.getUserName());
	// transferLogSaveRequest.setRemark(request.getRemark());
	// transferLogSaveRequest.setCreateTime(request.getCreateTime());
	// transferLogSaveRequest.setCreator(request.getCreator());
	// transferLogSaveRequest.setCreatorId(request.getCreatorId());
	// transferLogSaveRequest.setAssigneeName(request.getOrginUser().getUserName());
	// transferLogService.saveTransferLog(transferLogSaveRequest);
	//
	// return baseResponse;
	// }
	//
	// @Override
	// public BaseResponse<Void> callBackAfterEnding(String procInstId) {
	// if (StringUtils.isBlank(procInstId)) {
	// throw new
	// ServiceException(ErrorResponseEnum.REQUEST_PARAMETER_INVALID.getCode(),
	// "参数不能为空");
	// }
	//
	// // 判断流程实例是否已结束
	// ProcessInstance procInst =
	// this.runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
	// if (procInst != null) {
	// throw new
	// ServiceException(ErrorResponseEnum.REQUEST_PARAMETER_INVALID.getCode(),
	// "流程未结束！procInstId=" + procInstId);
	// }
	//
	// // 新增运行时实例
	// HistoricActivityInstanceQuery hisActInstQuery =
	// this.historyService.createHistoricActivityInstanceQuery();
	// HistoricTaskInstanceQuery hisTaskInstQuery =
	// this.historyService.createHistoricTaskInstanceQuery();
	//
	// // 可能重做多次，存在多次结束
	// HistoricActivityInstance hisActInst =
	// hisActInstQuery.processInstanceId(procInstId).activityType("endEvent")
	// .orderByHistoricActivityInstanceEndTime().desc().list().get(0);
	//
	// List<HistoricActivityInstance> hisActInstList =
	// hisActInstQuery.processInstanceId(procInstId).activityType("userTask")
	// .orderByHistoricActivityInstanceStartTime().desc().list();
	//
	// List<HistoricTaskInstance> hisTaskInstList =
	// hisTaskInstQuery.processInstanceId(procInstId)
	// .orderByHistoricTaskInstanceStartTime().desc().list();
	//
	// CallBackAfterEndingCmd cmd = new CallBackAfterEndingCmd(procInstId,
	// hisTaskInstList.get(0).getId(),
	// hisActInstList.get(0).getActivityId(),
	// hisActInst.getActivityId());
	// runCmd(cmd);
	// return new BaseResponse<>(new BaseResult<>(true, "流程重做成功"));
	// }
	//
	// @Override
	// public int getProcInstCurrVersion(String procInstId) {
	// int currVersion = 0;
	// if (StringUtils.isNotBlank(procInstId)) {
	// try {
	// HistoricProcessInstance hisProcInst =
	// this.historyService.createHistoricProcessInstanceQuery()
	// .processInstanceId(procInstId)
	// .singleResult();
	// ProcessDefinition procDef =
	// this.repositoryService.createProcessDefinitionQuery()
	// .processDefinitionId(hisProcInst.getProcessDefinitionId())
	// .singleResult();
	// currVersion = procDef.getVersion();
	// } catch (Exception e) {
	// }
	// }
	// return currVersion;
	// }
	//
	// @Override
	// public int getNextActivityBehavior(String procInstId, String
	// currActivityId)
	// {
	// int type = 0;
	// ProcessInstance procInst =
	// runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
	// if (procInst == null) {
	// throw new ServiceException(ErrorResponseEnum.INVOKE_ERROR.getCode(),
	// "流程实例不存在：procInstId=" + procInstId);
	// }
	//
	// ProcessDefinitionEntity def = (ProcessDefinitionEntity)
	// ((RepositoryServiceImpl) repositoryService)
	// .getDeployedProcessDefinition(procInst.getProcessDefinitionId());
	//
	// ActivityImpl activityImpl = def.findActivity(currActivityId);
	// // List<PvmTransition> pvmTransitionList =
	// activityImpl.getOutgoingTransitions();
	// // if(pvmTransitionList!=null && pvmTransitionList.size()==1){
	// // PvmActivity ac = pvmTransitionList.get(0).getDestination();
	// Object acType = activityImpl.getProperty("type");
	// if ("userTask".equals(acType)) {
	// type = 1;
	// } else if ("multiInstance".equals(acType)) {
	// type = 2;
	// } else if ("exclusiveGateway".equals(acType)) {
	// type = 3;
	// } else if ("subProcess".equals(acType)) {
	// type = 4;
	// } else if ("parallelGateway".equals(acType)) {
	// type = 5;
	// } else if ("intermediateTimer".equals(acType)) {
	// type = 6;
	// } else if ("serviceTask".equals(acType)) {
	// type = 7;
	// } else if ("intermediateThrowEvent".equals(acType)) {
	// type = 8;
	// } else if ("scriptTask".equals(acType)) {
	// type = 9;
	// } else if ("intermediateCatchEvent".equals(acType)) {
	// type = 10;
	// } else if ("intermediateSignalCatch".equals(acType)) {
	// type = 11;
	// } else if ("receiveTask".equals(acType)) {
	// type = 12;
	// } else if ("manualTask".equals(acType)) {
	// type = 13;
	// }
	// // }
	//
	// return type;
	// }
	//
	// @Override
	// public void sendTasks(List<SendVO> sendVOs) {
	// // 更新审批意见状态为 发布状态
	// final SendVO firstVO = sendVOs.get(0);
	// OpinionQueryRequest request = new OpinionQueryRequest();
	// request.setTaskId(firstVO.getCurTaskId());
	// request.setProcInstId(firstVO.getProcInstId());
	// request.setUserId(Long.parseLong(firstVO.getCurUserId()));
	// BaseResponse<OpinionResponse> opinionResponse =
	// this.opinionService.getOpinion(request);
	// OpinionResponse opinion = opinionResponse.getResult().getData();
	// if (opinionResponse.getResult().isSuccess()) {
	// OpinionSaveOrUpdateReqeust opinionSaveOrUpdateReqeust = new
	// OpinionSaveOrUpdateReqeust();
	// ObjUtil.objectToObject(opinion, opinionSaveOrUpdateReqeust);
	// opinionSaveOrUpdateReqeust.setOpinionStatus(Opinion.STATUS_SUBMIT);
	// this.opinionService.update(opinionSaveOrUpdateReqeust);
	// }
	//
	// // 发送处理
	// Task task =
	// taskService.createTaskQuery().taskId(firstVO.getCurTaskId()).singleResult();
	// if (task == null) {
	// throw new ServiceException(ErrorResponseEnum.INVOKE_ERROR.getCode(),
	// "任务不存在：curTaskId=" + firstVO.getCurTaskId());
	// }
	// //设置任务流程变量
	// if (firstVO.getVariables() == null) {
	// firstVO.setVariables(new HashMap<String, Object>());
	// }
	//
	// // 完成当前任务
	// String outcome = firstVO.getPreExclusiveGatewayId();
	// if (StringUtils.isBlank(outcome)) {
	// outcome = firstVO.getPreActivityId();
	// }
	//
	// firstVO.getVariables().put("outcome", outcome);//outcome用于控制多个出口的情况
	// taskService.setVariablesLocal(firstVO.getCurTaskId(),
	// firstVO.getVariables());//限制变量的生命周期在本任务内
	// taskService.complete(firstVO.getCurTaskId(), firstVO.getVariables());
	//
	// // 根据发送设置，指派下一任务处理人
	// // 处理group的情况，人的情况不需要处理
	// for (SendVO sendVO : sendVOs) {
	// if (StringUtils.isBlank(sendVO.getNextAssigneeAccount())) {
	// // 送结束，或使用流程变量设置assignee
	// return;
	// }
	//
	// String[] nextAssigneeAccountArray =
	// sendVO.getNextAssigneeAccount().split(",");
	// for (int i = 0; i < nextAssigneeAccountArray.length; i++) {
	// String naa = nextAssigneeAccountArray[i];
	// List<Task> taskList =
	// taskService.createTaskQuery().processInstanceId(sendVO.getProcInstId()).taskCandidateUser(naa).list();
	//
	// if (taskList != null && !taskList.isEmpty()) {
	// //boolean assigneeResult = false;
	// for (Task nextTask : taskList) {
	// if (nextTask.getTaskDefinitionKey().endsWith(sendVO.getNextActivityId())
	// && StringUtils.isBlank(nextTask.getAssignee())) {
	// BaseResponse<BossUserResponse> response =
	// userService.getBossUserByAccount(naa);
	// if (this.hasActivityRight(nextTask.getProcessDefinitionId(),
	// nextTask.getTaskDefinitionKey(), response.getResult().getData())) {
	// taskService.claim(nextTask.getId(), naa);
	// try {
	// //判断nextTask的执行者是否配置了代理人
	// ProcessDefinitionQuery procDefQuery =
	// repositoryService.createProcessDefinitionQuery();
	// ProcessDefinition procDef =
	// procDefQuery.processDefinitionId(nextTask.getProcessDefinitionId()).singleResult();
	// BaseResponse<DelegationResponse> delegationResponse =
	// delegationService.find(procDef.getKey(), naa, new Date());
	// if (delegationResponse.getResult().isSuccess()) {
	// taskService.delegateTask(nextTask.getId(),
	// delegationResponse.getResult().getData().getAgencyAccount());
	// // huangza 修复：把代理的默认状态 PENDING 改为 RESOLVED
	// activitiCommonService.updateBy(DelegationState.RESOLVED.toString(),
	// nextTask.getId(), nextTask.getProcessInstanceId());
	// }
	// } catch (Exception e) {
	// logger.error(e.getMessage(), e);
	// }
	// } else {
	// throw new ServiceException(ErrorResponseEnum.INVOKE_ERROR.getCode(),
	// "发送任务失败：下一步【" + nextTask.getName() + "】执行人【" +
	// response.getResult().getData().getUserName() + "】没有执行权限！");
	// }
	//
	// //assigneeResult = true;
	// break;
	// }
	// }
	//
	// }
	// }
	// }
	//
	// }
	//
	// @Override
	// public BaseResponse<Void> signal(SignalRequest request) {
	// BaseResponse<Void> response = new BaseResponse<>();
	// Map<String, Object> processVariables = new HashMap<>();
	// if (null != request.getVariables()) {
	// processVariables = request.getVariables();
	// }
	// runtimeService.signal(request.getExecutionId(), processVariables);
	// return response;
	// }
	//
	// @Override
	// public BaseResponse<Void> canSend(FormCanSendRequest request) throws
	// IllegalAccessException, InvocationTargetException {
	// BaseResponse<Void> response = new BaseResponse();
	// TaskVO taskVO = this.findTask(request.getTaskId());
	// if (taskVO == null) {
	// response.setResult(new BaseResult<>(false, "当前任务已经审批完成过"));
	// } else {
	// response.setResult(new BaseResult<>(true, "可以发送"));
	// }
	// return response;
	//
	// }
	//
	@Override
	public EndEventType getEndEventType(ActivityResponse nextActivity) {
		if (!StringUtils.equals(ActivityType.END_EVENT.getValue(), nextActivity.getActivityType())) {
			return null;
		}

		if (StringUtils.equals(EndEventType.PASS_END_EVENT.getEventName(), nextActivity.getActivityId())) {
			return EndEventType.PASS_END_EVENT;
		}

		if (StringUtils.equals(EndEventType.REJECT_END_EVENT.getEventName(), nextActivity.getActivityId())) {
			return EndEventType.REJECT_END_EVENT;
		}

		if (StringUtils.equals(EndEventType.CANCEL_END_EVENT.getEventName(), nextActivity.getActivityId())) {
			return EndEventType.CANCEL_END_EVENT;
		}

		log.warn("找不到节点结束类型, 错误参数 : {} ", nextActivity.getActivityId());
		throw new SystemException("找不到节点结束类型");
	}

	@Override
	public ProcessInstanceResponse startProcess(String account, String assignee, String procDefKey, String title,
			List<String> businessKeys, Map<String, Object> variables) {

		if (StringUtils.isNotBlank(account) && !systemUserService.existByAccount(account)) {
			throw new SystemException("用户不存在 : " + account);
		}

		if (StringUtils.isNotBlank(assignee) && !systemUserService.existByAccount(assignee)) {
			throw new SystemException("用户不存在 : " + account);
		}

		// TODO 判断业务是否已开启过流程
		// BaseResponse<ProcessStartResponse> response = new BaseResponse<>();
		//
		// ProcessInfoGetRequest processInfoGetRequest = new
		// ProcessInfoGetRequest();
		// processInfoGetRequest.setOrderId(request.getBizId());
		// processInfoGetRequest.setProcessType(request.getProcDefKey());
		// BaseResponse<ProcessInfoResponse> processInfoResponse =
		// processInfoService.getProcessInfo(processInfoGetRequest);

		// if (null != processInfoResponse.getResult().getData()) {
		// response.setResult(new BaseResult<>(true, "该业务已启动过流程"));
		// processInstanceVO =
		// workflowManagerService.findProcessInstance(processInfoResponse.getResult().getData().getProcessInstanceId());
		// } else {

		String busiKey = procDefKey + ":" + businessKeys.stream().collect(Collectors.joining(":"));

		ProcessInstanceResponse processInstanceResponse = this.startProcessInstance(procDefKey, busiKey, title,
				account, assignee, variables);

		// TaskVO taskVO = this.getFirstTask(processInstanceVO.getId());
		//
		// BaseResponse<Void> commitTaskResponse = null;
		// if (request.isCompleteFirstTask()) {
		// CommitRequest commitRequest = new CommitRequest();
		// commitRequest.setProcInstId(processInstanceVO.getId());
		// commitRequest.setTaskId(taskVO.getId());
		// commitRequest.setCreatorId(userResponse.getResult().getData().getId());
		// commitRequest.setOperateType(FormRightResponse.RIGHT_CODE_APPROVAL);
		// commitTaskResponse = this.commitTask(commitRequest);
		// }
		//
		// ProcessStartResponse processStartResponse = new
		// ProcessStartResponse();
		// // 如果不完成第一个节点或完成第一个节点时出错，则返回formEdit的链接
		// if (!request.isCompleteFirstTask() || (null != commitTaskResponse &&
		// !commitTaskResponse.getResult().isSuccess())) {
		// String url = "/workflow/form/formEdit?taskId=" + taskVO.getId();
		// processStartResponse.setUrl(url);
		// } else { // 成功完成第一个节点
		// processStartResponse.setUrl("");
		// taskVO = this.getProcInstCurrTask(processInstanceVO.getId());
		// }
		// processStartResponse.setTaskId(taskVO.getId());
		// processStartResponse.setProcInstId(processInstanceVO.getId());
		// processStartResponse.setStartActivityId(taskVO.getTaskDefinitionKey());
		// processStartResponse.setStartTime(processInstanceVO.getStartTime());
		// response.setResult(new BaseResult<>(processStartResponse));
		return processInstanceResponse;
	}

	@Override
	public ProcessInstanceResponse startProcess(String account, String procDefKey, String title,
			List<String> businessKeys, Map<String, Object> variables) {
		return startProcess(account, null, procDefKey, title, businessKeys, variables);
	}

	//
	// /**
	// * 启动流程
	// *
	// * @param user
	// * @param project
	// * @param busiKey
	// * @param title
	// * @param processType
	// * @return
	// */
	// private BaseResponse<ProcessStartResponse> startProcess(User user,
	// Project
	// project, String busiKey, String title, String processType) {
	//
	//
	// // cdProcess = this.startProcessInstance(processType, busiKey, title,
	// user,
	// variables, urlParam);
	// //
	// // if
	// (cdOrderProcessInfoService.findCtCdOrderProcessByOrderIdAndProccessType(project.getProjectId(),
	// processType) != null) {
	// // throw new ServiceException("已订单已启动过流程，请从订单列表查看!");
	// // }
	// //
	// // cdOrderProcessInfoService.addProcessInfo(project.getProjectId(),
	// processType, cdProcess, "0");
	// // taskId = workflowProcessor.getFirstTaskId(cdProcess.getId());
	// // log.error("启动车贷流程失败: " + processType);
	// // throw new ServiceException(e);
	// // return taskId;
	// return null;
	// }
	//
	// @Override
	// public List<SystemUser> getNextActivityAssigneeAccount(String
	// procInstId,String activityId) {
	// BaseResponse<Map<String, List<BossUserResponse>>> response = new
	// BaseResponse<>();
	// TaskVO task = this.findTask(request.getTaskId());
	// if (task == null) {
	// throw new ServiceException(ErrorResponseEnum.SYSTEM_ERROR.getCode(),
	// "当前环节已经审批过！");
	// }
	// String activitiId = task.getTaskDefinitionKey();
	//
	// // 查询下一环节
	// List<ActivityResponse> nextActivity = this.getNextActivity(procInstId,
	// activitiId);
	//
	// // 查询后续处理人
	// Map<String, List<BossUserResponse>> userMap = new TreeMap<>();
	// for (ActivityVO activityVO : nextActivity) {
	// SelectableUserListGetRequest selectableUserListGetRequest = new
	// SelectableUserListGetRequest();
	// List<AssigneeResponse> assigneeResponseList = new ArrayList<>();
	// ObjUtil.listObjectToListObject(activityVO.getAssigneeList(),
	// assigneeResponseList, AssigneeResponse.class);
	// selectableUserListGetRequest.setAssigneeList(assigneeResponseList);
	// BaseResponse<List<BossUserResponse>> bossUserResponseListResponse =
	// this.getSelectableUserList(selectableUserListGetRequest);
	// userMap.put(activityVO.getActivityId(),
	// bossUserResponseListResponse.getResult().getData());
	// }
	// response.setResult(new BaseResult<>(userMap));
	// return response;
	// }

	// @Override
	// public BaseResponse<String>
	// getAssigneeDefinition(AssigneeDefinitionGetRequest request) {
	// BaseResponse<String> response = new BaseResponse<>();
	// StringBuilder sb = new StringBuilder();
	// List<ActivityVO> activityVOS =
	// this.getActivityVOByProcInstId(request.getProcInstId());
	// for (ActivityVO activityVO : activityVOS) {
	// if (activityVO.getActivityName().equals(request.getTaskName())) {
	// for (int i = 0; i < activityVO.getAssigneeList().size(); i++) {
	// if
	// (StringUtils.isEmpty(activityVO.getAssigneeList().get(i).getAssigneeName()))
	// continue;
	// sb.append(activityVO.getAssigneeList().get(i).getAssigneeName());
	// if (i != activityVO.getAssigneeList().size() - 1) {
	// sb.append("/");
	// }
	// }
	// break;
	// }
	// }
	// response.setResult(new BaseResult<>(sb.toString()));
	// return response;
	// }
	//
	// @Override
	// public BaseResponse<Void> setProcessVariable(ProcessVariableSetRequest
	// request) {
	// this.setVariable(request.getProcInstId(), request.getVarName(),
	// request.getVarValue());
	// return new BaseResponse<>();
	// }
	//
	// @Override
	// public BaseResponse<Object>
	// isCustomFormEditUrl(CustomFormEditUrlJudgeRequest
	// request) {
	// BaseResponse<Object> response = new BaseResponse<>();
	// List<HistoricVariableInstance> historicVariableInstances =
	// historyService.createHistoricVariableInstanceQuery().processInstanceId(request.getProcInstId()).list();
	// for (HistoricVariableInstance historicVariableInstance :
	// historicVariableInstances) {
	// if
	// (WorkflowConst.FORM_EDIT_URL.equals(historicVariableInstance.getVariableName()))
	// {
	// String customFormEdit = getCustomFormEditUrl(request,
	// historicVariableInstance);
	// response.setResult(new BaseResult<>(customFormEdit));
	// return response;
	// }
	// }
	// response.setResult(new BaseResult<>(false, ""));
	// return response;
	// }
	//
	@Override
	public List<TrackingResponse> findProcessTrackingByProcInstId(String procInstId) {
		List<Opinion> opinions = opinionService.findAllByProcInstId(procInstId);

		List<ActivityResponse> activityResponses = getTraceListByProcInstId(procInstId);

		List<TrackingResponse> trackingResponses = activityResponses.stream().map(x -> {
			TrackingResponse trackingResponse = new TrackingResponse();
			BeanUtils.copyProperties(x, trackingResponse);
			return trackingResponse;
		}).collect(Collectors.toList());

		for (TrackingResponse trackingResponse : trackingResponses) {
			String taskId = null;
			if (null != trackingResponse.getTaskId()) {
				taskId = trackingResponse.getTaskId();
			} else {
				taskId = trackingResponse.getActivityId();
			}
			for (Opinion opinion : opinions) {
				if (StringUtils.equals(taskId, opinion.getTaskId())) {
					BeanUtils.copyProperties(opinion, trackingResponse);
				}
			}
		}

		return trackingResponses;
	}

	// * 职责：根据流程实例获取流程跟踪列表
	// *
	// * @param procInstId
	// * 流程实例id
	// */
	List<ActivityResponse> getTraceListByProcInstId(String procInstId) {
		HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
		HistoricProcessInstance hisProcInst = historicProcessInstanceQuery.processInstanceId(procInstId).singleResult();

		// 历史已完成的节点
		List<HistoricActivityInstance> historicActivityInstances = historyService.createHistoricActivityInstanceQuery()
				.processInstanceId(procInstId).orderByHistoricActivityInstanceStartTime().desc().list();

		List<ActivityResponse> activityResponses = Lists.newArrayList();

		for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
			// 过滤非(用户节点/结束节点/serviceTask)，即开始、条件等节点
			if (!historicActivityInstance.getActivityType().equals("userTask")
					&& !historicActivityInstance.getActivityType().equals("endEvent")
					&& !historicActivityInstance.getActivityType().equals("serviceTask")
					&& !historicActivityInstance.getActivityType().equals("intermediateTimer")) {
				continue;
			}

			ActivityResponse activityResponse = new ActivityResponse();
			BeanUtils.copyProperties(historicActivityInstance, activityResponse);
			ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
					.getDeployedProcessDefinition(hisProcInst.getProcessDefinitionId());

			if (historicActivityInstance.getTaskId() != null) {
				HistoricTaskInstanceQuery historicTaskInstanceQuery = historyService.createHistoricTaskInstanceQuery();
				HistoricTaskInstance historicTaskInstance = historicTaskInstanceQuery.taskId(
						historicActivityInstance.getTaskId()).singleResult();
				boolean isCountersign = false;

				// 判断该活动是否正常结束
				if (historicTaskInstance.getEndTime() != null && historicTaskInstance.getDeleteReason() != null
						&& !historicTaskInstance.getDeleteReason().equals("completed")) {
					// 该任务被回退或流程实例被“删除”了
					String activityName = StringUtils.EMPTY;
					if (StringUtils.isBlank(hisProcInst.getDeleteReason())) {
						// 判断是否会签节点
						ActivityImpl actImpl = processDefinitionEntity.findActivity(historicTaskInstance
								.getTaskDefinitionKey());
						if (actImpl.getActivityBehavior() instanceof MultiInstanceActivityBehavior) {
							isCountersign = true;
							activityName = activityResponse.getActivityName() + "(已放弃)";
							// 对于已放弃的会签任务，不希望让用户觉得被处理的错觉
							activityResponse.setEndTime(null);
							activityResponse.setDurationInMillis(null);
							// 把这个活动隐藏掉，不需要显示所有会签人员
							continue;
						} else {
							activityName = activityResponse.getActivityName() + "(已回退)";
						}
					} else {
						activityName = activityResponse.getActivityName() + "(已删除)";
					}
					if (historicTaskInstance.getDeleteReason().indexOf("endevent") != -1) {
						activityName = activityResponse.getActivityName() + "(已重做)";
					}

					activityResponse.setActivityName(activityName);
					activityResponse.setAssignee(historicTaskInstance.getAssignee());
					if (!isCountersign) {
						activityResponse.setEndTime(historicTaskInstance.getEndTime());
						activityResponse.setDurationInMillis(historicTaskInstance.getDurationInMillis());
					}
				}
				// 判断是否代理
				activityResponse.setOwner(historicTaskInstance.getOwner());
				// 判断执行者为空的情况
				if (StringUtils.isBlank(activityResponse.getAssignee())) {
					activityResponse.setAssignee(historicTaskInstance.getAssignee());
				}
				// 判断结束时间为空的情况
				if (activityResponse.getEndTime() == null && !isCountersign) {
					activityResponse.setEndTime(historicTaskInstance.getEndTime());
					activityResponse.setDurationInMillis(historicTaskInstance.getDurationInMillis());
				}
			}

			if (!historicActivityInstance.getActivityType().equals("endEvent")) {

				if (StringUtils.isNotBlank(activityResponse.getAssignee())) {

					activityResponse
							.setAssigneeName(systemUserService.findNameByAccount(activityResponse.getAssignee()));

				} else {
					activityResponse.setAssigneeName("(无)");
				}

				activityResponse.setOwnerName(systemUserService.findNameByAccount(activityResponse.getOwner()));
			}

			// 识别子流程
			if (!activityResponse.getProcessInstanceId().equals(activityResponse.getExecutionId())) {
				for (HistoricActivityInstance haInst : historicActivityInstances) {
					if (haInst.getActivityType().equalsIgnoreCase("subProcess")
							&& haInst.getExecutionId().equals(activityResponse.getExecutionId())) {
						activityResponse.setActivityName("[ " + haInst.getActivityName() + " ] "
								+ activityResponse.getActivityName());
					}
				}
			}

			activityResponses.add(activityResponse);
		}

		return activityResponses;
	}

	//
	// /**
	// * 职责：根据流程实例获取流程跟踪图片
	// *
	// * @param procInstId
	// * 流程实例id
	// */
	@Override
	public InputStream findProcessTrackingImageByProcInstId(String procInstId) {
		GenerateFlowImageCmd generateFlowImageCmd = new GenerateFlowImageCmd(StringUtils.trimToEmpty(procInstId));
		return ((RuntimeServiceImpl) runtimeService).getCommandExecutor().execute(generateFlowImageCmd);
	}

	// @Override
	// public BaseResponse<String> rejectToFirstTask(RejectToFirstTaskRequest
	// request) {
	// FormRejectRequest formRejectRequest = new FormRejectRequest();
	// ObjUtil.objectToObject(request, formRejectRequest);
	// formRejectRequest.setProcInstId(request.getProcInstId());
	// TaskVO taskVO = this.getProcInstCurrTask(request.getProcInstId());
	// formRejectRequest.setTaskId(taskVO.getId());
	// formRejectRequest.setRejectType(RejectType.WITHDRAW);
	// BaseResponse<List<TaskVO>> passedTaskVOResponse =
	// this.getPassedTaskVO(formRejectRequest);
	// List<TaskVO> passedVOs = passedTaskVOResponse.getResult().getData();
	// if (CollectionUtils.isEmpty(passedVOs)) {
	// throw new ServiceException(ErrorResponseEnum.INVOKE_ERROR.getCode(),
	// "提回第一个节点失败");
	// } else {
	// TaskVO firstTask = passedVOs.get(passedVOs.size() - 1);
	// formRejectRequest.setSelectedTaskId(firstTask.getId());
	// return reject(formRejectRequest);
	// }
	// }
	//
	// private String getCustomFormEditUrl(CustomFormEditUrlJudgeRequest
	// request,
	// HistoricVariableInstance historicVariableInstance) {
	// String busiKey = getProcInstBusiKey(request.getProcInstId());
	// // 获取表单参数
	// BaseResponse<FormInstParamResponse> formParamResponse =
	// procInstFormParamService.findByProcInstId(request.getProcInstId());
	// String actionIdName =
	// formParamResponse.getResult().getData().getActionIdName();
	// String[] split = StringUtils.split(busiKey, ".");
	// StringBuilder sb = new StringBuilder();
	// sb.append(historicVariableInstance.getValue());
	// sb.append("?").append(actionIdName).append("=").append(split[1]);
	// return sb.toString();
	// }

	@Override
	public Page<ProcessInstanceResponse> listProcessInstance(PageSearcher<ProcessInstanceSearchRequest> request) {
		return processInstanceRepository.listProcessInstance(request.getSearchCondition(), request.getPageable());

		// List<ProcessInstance> procInstResponseList =
		// procInstMapper.listProcInst(ObjUtil.objectToMap(request));
		// List<ProcessInstanceVO> procInstVOResponseList = new
		// ArrayList<>(procInstResponseList.size());
		// ObjUtil.listObjectToListObject(procInstResponseList,
		// procInstVOResponseList,
		// ProcessInstanceVO.class);
		// for (ProcessInstanceVO procInstVO : procInstVOResponseList) {
		// // 设置实例状态
		// String procInstStatus = null;
		// if (procInstVO.getEndendProcessTime() != null) {
		// // 已结束
		// procInstStatus = StringUtils.isBlank(procInstVO.getDeleteReason()) ?
		// ProcessInstanceVO.PROCESS_STATUS_ENDING :
		// ProcessInstanceVO.PROCESS_STATUS_DELETED;
		// } else {
		// // 流转中
		// List<Execution> exeList =
		// runtimeService.createExecutionQuery().processInstanceId(procInstVO.getId()).list();
		// ExecutionEntity exe = (ExecutionEntity) exeList.get(0);
		// procInstStatus = exe.isSuspended() ?
		// ProcessInstanceVO.PROCESS_STATUS_SUSPEND
		// : ProcessInstanceVO.PROCESS_STATUS_ACTIVATE;
		// }
		// procInstVO.setStatus(procInstStatus);
		// }
		//
		// loadCategoryName(procInstVOResponseList);
		// loadStartUserName(procInstVOResponseList);
		//
		// PageInfo<ProcessInstance> pageInfo = new
		// PageInfo<>(procInstResponseList);
		// return new DatatablesPageResponse<>(request.getDraw(),
		// Long.toString(pageInfo.getTotal()), procInstVOResponseList);
	}

}
